/**
 * 
 */
package com.jolestar.yayaweibotong.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;

import weibo4j.Paging;
import weibo4j.RetweetDetails;
import weibo4j.Status;
import weibo4j.User;
import weibo4j.Weibo;
import weibo4j.WeiboException;

import com.jolestar.yayaweibotong.ApiReachLimitException;
import com.jolestar.yayaweibotong.NetworkException;
import com.jolestar.yayaweibotong.ServiceType;
import com.jolestar.yayaweibotong.SkipCurrentStatusException;
import com.jolestar.yayaweibotong.YayaException;
import com.jolestar.yayaweibotong.dao.AccountDomain;
import com.jolestar.yayaweibotong.dao.RetweetDomain;
import com.jolestar.yayaweibotong.dao.StatusDomain;

/**
 * @author jolestar@gmail.com
 * 
 */
public class SinaStatusService extends AbstractStatusService<Weibo> {

	private static final Logger log = Logger.getLogger(SinaStatusService.class
			.getName());

	/**
	 * 
	 */
	public SinaStatusService() {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.jolestar.yayaweibotong.service.StatusService#getLatestStatuses(long)
	 */
	@Override
	public List<StatusDomain> getLatestStatuses(AccountDomain account,
			String sinceId) {
		Weibo weibo = this.getOrCreateInstance(account);
		Paging page = new Paging();
		if (sinceId != null&&this.existsStatus(ServiceType.sina, sinceId)) {
			page.setSinceId(Long.parseLong(sinceId));
			page.setCount(5);
		}else{
			page.setCount(1);
		}
		try {
			List<Status> statuses = weibo.getUserTimeline(page);
			if (statuses == null || statuses.isEmpty()) {
				return Collections.emptyList();
			}
			List<StatusDomain> results = new ArrayList<StatusDomain>(
					statuses.size());
			for (Status status : statuses) {
				StatusDomain statusDomain = this.getStatusDomain(
						ServiceType.sina, Long.toString(status.getId()));
				if (statusDomain == null) {
					statusDomain = this.convert(status, account, weibo);
				}
				statusDomain.save();
				results.add(statusDomain);
			}
			return results;
		} catch (WeiboException e) {
			if (e.getStatusCode() == 403) {
				throw new ApiReachLimitException(e);
			}
			if(e.getCause() instanceof IOException){
				throw new NetworkException(e);
			}
			throw new YayaException(e);
		}
	}

	private StatusDomain convert(Status status, AccountDomain account,
			Weibo weibo) throws WeiboException {
		StatusDomain statusDomain = new StatusDomain(ServiceType.sina,
				Long.toString(status.getId()), account);
		statusDomain.setText(status.getText());
		String originalPic = status.getOriginalPic();
		if (!StringUtils.isBlank(originalPic)) {
			statusDomain.setThumbnailPic(status.getThumbnailPic());
			statusDomain.setBmiddlePic(status.getBmiddlePic());
			statusDomain.setOriginalPic(originalPic);
			try {
				statusDomain.setOriginalPicShortUrl(weibo
						.getShortUrl(originalPic));
			} catch (WeiboException e) {
				log.log(Level.SEVERE, e.getMessage(), e);
			}
		}
		if (status.isRetweet()) {
			RetweetDetails rtDetails = status.getRetweetDetails();
			RetweetDomain retweet = new RetweetDomain(ServiceType.sina,
					statusDomain, rtDetails.getRetweetId(), rtDetails
							.getRetweetingUser().getName(), rtDetails
							.getRetweetingUser().getScreenName(),
					rtDetails.getText());
			String retOriginalPic = rtDetails.getOriginalPic();
			if (!StringUtils.isBlank(retOriginalPic)) {
				retweet.setThumbnailPic(rtDetails.getThumbnailPic());
				retweet.setBmiddlePic(rtDetails.getBmiddlePic());
				retweet.setOriginalPic(retOriginalPic);
				try {
					retweet.setOriginalPicShortUrl(weibo
							.getShortUrl(retOriginalPic));
				} catch (WeiboException e) {
					log.log(Level.SEVERE, e.getMessage(), e);
				}
			}
			statusDomain.setRetweet(retweet);
		}
		statusDomain.setCreateAt(status.getCreatedAt());
		return statusDomain;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.jolestar.yayaweibotong.service.StatusService#updateStatus(com.jolestar
	 * .yayaweibotong.dao.StatusDomain)
	 */
	@Override
	public StatusDomain updateStatus(AccountDomain account, StatusDomain status) {
		Weibo weibo = this.getOrCreateInstance(account);
		try {
			Status newStatus = weibo.updateStatus(status
					.formatStatus(ServiceType.sina.getStatusLengthLimit()));
			StatusDomain result = this.convert(newStatus, account, weibo);
			result.setSynced(true);
			result.setSyncedAt(new Date());
			result.setOriginalStatus(status);
			result.save();
			return result;
		} catch (WeiboException e) {
			// TODO 细分
			if (e.getStatusCode() == 403) {
				throw new ApiReachLimitException(e);
			} else if (e.getStatusCode() == 400) {
				throw new SkipCurrentStatusException(e);
			}
			if(e.getCause() instanceof IOException){
				throw new NetworkException(e);
			}
			throw new YayaException(e);
		}
	}

	@Override
	public void updateAccount(AccountDomain account) {
		Weibo weibo = this.getOrCreateInstance(account);
		try {
			User user = weibo.showUser(account.getOriginalId());
			account.setScreenName(user.getScreenName());
			account.setName(user.getName());
			account.setProfileImage(user.getProfileImageURL().toExternalForm());
			account.setDomain(user.getDomain());
			account.setCreateAt(user.getCreatedAt());
			account.save();
		} catch (WeiboException e) {
			throw new YayaException(e);
		}
	}

	@Override
	protected Weibo createInstance(AccountDomain account) {
		Weibo weibo = new Weibo();
		weibo.setOAuthConsumer(ServiceType.sina.getApiKey(),
				ServiceType.sina.getApiSecret());
		weibo.setOAuthAccessToken(account.getToken(), account.getTokenSecret());
		return weibo;
	}

}
